#include "CSDLInputHandler.h"
#include "../../SDL/include/SDL/SDL.h"


CSDLInputHandler::CSDLInputHandler(LivingObject *pPlayer, KeyMapping *keyMapping)
{
	if(pPlayer == NULL)
	{
		writeDebugOutput("The player pointer was NULL! Thats bad - aborting!");
	}

	if(SDL_WasInit(SDL_INIT_VIDEO) == 0) // Video inits also the event system
	{
		if(SDL_InitSubSystem(SDL_INIT_VIDEO) != 0)
		{
			writeDebugOutput("SDL_INIT_VIDEO failed to initialise! Thats bad - aborting!");
			//TODO: throw exception
		}
	}

	SDL_WM_GrabInput(SDL_GRAB_ON);
	SDL_ShowCursor(SDL_DISABLE);
	m_pPlayer = pPlayer;
	mapInputConfigToSDLEnum(keyMapping);
        m_isInputActivated = false;
        m_bContinue = true;
}

CSDLInputHandler::~CSDLInputHandler()
{
	if(SDL_WasInit(SDL_INIT_VIDEO) != 0)
	{
		SDL_QuitSubSystem(SDL_INIT_VIDEO);
	}
}

bool CSDLInputHandler::checkEvents()
{
	// This function is called every time a new frae is rendered, so it is ok do calc the fps here
	// But we should move the next if() to somewhere else when we have time (InputFrameListener shuld be SDL free..)
	m_lFrame++;
	if(m_TimerSecond.getMilliseconds() > 1000)
	{
		double dFPS = 0.0;
		char carrFPS[32];
		dFPS = (double)m_lFrame / ((double)m_TimerFPS.getMilliseconds() / 1000.0);

                //sprintf_s(carrFPS,32,"%lf FPS",dFPS);
                sprintf(carrFPS,"%lf FPS",dFPS);

		SDL_WM_SetCaption(carrFPS, NULL);
		
		m_TimerSecond.reset(); // reset the timer so we can count to 1sec again
	}

	while(SDL_PollEvent(&m_evSDLEvent))
	{
                if(m_evSDLEvent.type == SDL_KEYDOWN && m_isInputActivated)
		{
			processKeyDown(&m_evSDLEvent);
		}
                else if(m_evSDLEvent.type == SDL_KEYUP && m_isInputActivated)
		{
			processKeyUp(&m_evSDLEvent);
		}
                else if(m_evSDLEvent.type == SDL_MOUSEBUTTONDOWN && m_isInputActivated)
		{
			processMouseDown(&m_evSDLEvent);
		}
                else if(m_evSDLEvent.type == SDL_MOUSEBUTTONUP && m_isInputActivated)
		{
			processMouseUp(&m_evSDLEvent);
		}
                else if(m_evSDLEvent.type == SDL_MOUSEMOTION && m_isInputActivated)
		{
			processMouseMove(&m_evSDLEvent);
		}
	}
	return true;
}

void CSDLInputHandler::processKeyUp(SDL_Event *m_evSDLEvent)
{
	if(m_evSDLEvent->key.keysym.sym == m_keyTable.Right)
	{
                m_pPlayer->moveX(-1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Left)
	{
                m_pPlayer->moveX(1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Up)
	{
                m_pPlayer->moveY(-1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Down)
	{
                m_pPlayer->moveY(1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Backward)
	{
                m_pPlayer->moveZ(-1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Forward)
	{
                m_pPlayer->moveZ(1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Menu)
	{
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Run)
	{
		m_pPlayer->setSprintMove(false);
	}
}
void CSDLInputHandler::processKeyDown(SDL_Event *m_evSDLEvent)
{
	if(m_evSDLEvent->key.keysym.sym == m_keyTable.Right)
	{
                m_pPlayer->moveX(1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Left)
	{
                m_pPlayer->moveX(-1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Up)
	{
                m_pPlayer->moveY(1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Down)
	{
                m_pPlayer->moveY(-1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Backward)
	{
                m_pPlayer->moveZ(1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Forward)
	{
                m_pPlayer->moveZ(-1);
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Menu)
	{
		writeDebugOutput("COisBufferedInputHandler::keyPressed(): catching ESC");
		m_bContinue = false;
	}
	else if(m_evSDLEvent->key.keysym.sym == m_keyTable.Run)
	{
		m_pPlayer->setSprintMove(true);
	}
}
void CSDLInputHandler::processMouseUp(SDL_Event *m_evSDLEvent)
{
	;
}
void CSDLInputHandler::processMouseDown(SDL_Event *m_evSDLEvent)
{
	;
}
void CSDLInputHandler::processMouseMove(SDL_Event *m_evSDLEvent)
{
        m_pPlayer->rotate( m_evSDLEvent->motion.xrel, m_evSDLEvent->motion.yrel, 0);
}

void CSDLInputHandler::mapInputConfigToSDLEnum(KeyMapping *keyMapping)
{
	// This is a default map - uncomment for debugging reasons only!
//	m_keyTable.Forward = SDLK_w;
//	m_keyTable.Backward = SDLK_s;
//	m_keyTable.Up = SDLK_SPACE;
//	m_keyTable.Down = SDLK_LCTRL;
//	m_keyTable.Left = SDLK_a;
//	m_keyTable.Right = SDLK_d;
//	m_keyTable.Menu = SDLK_ESCAPE;
//	m_keyTable.Run = SDLK_LSHIFT;

        // Map the keys
        m_keyTable.Forward = getSDLEnum(keyMapping->forward);
        m_keyTable.Backward = getSDLEnum(keyMapping->backward);
        m_keyTable.Up = getSDLEnum(keyMapping->up);
        m_keyTable.Down = getSDLEnum(keyMapping->down);
        m_keyTable.Left = getSDLEnum(keyMapping->left);
        m_keyTable.Right = getSDLEnum(keyMapping->right);
        m_keyTable.Menu = getSDLEnum(keyMapping->menu);
        m_keyTable.Run = getSDLEnum(keyMapping->run);
}

SDLKey CSDLInputHandler::getSDLEnum(std::string key)
{
	// if the first char is a lower chase letter, we have a single char that we can cast directly
        if( (int)key.c_str()[0] >= 97 && (int)key.c_str()[0] <= 122 )
	{
                return (SDLKey)((int)key.c_str()[0]);
	}
	else
	{
                if(key.compare("Shift") == 0)
		{
                        return SDLK_LSHIFT;
		}
                else if(key.compare("Ctrl") == 0)
		{
			return SDLK_LCTRL;
		}
                else if(key.compare("ESC") == 0)
		{
			return SDLK_ESCAPE;
		}
                else if(key.compare("ALT") == 0)
		{
			return SDLK_LALT;
		}
                else if(key.compare("Tab") == 0)
		{
			return SDLK_TAB;
		}
                else if(key.compare("Return") == 0)
		{
			return SDLK_RETURN;
		}
                else if(key.compare("Up") == 0)
		{
			return SDLK_UP;
		}
                else if(key.compare("Down") == 0)
		{
			return SDLK_DOWN;
		}
                else if(key.compare("Left") == 0)
		{
			return SDLK_LEFT;
		}
                else if(key.compare("Right") == 0)
		{
			return SDLK_RIGHT;
		}
                else if(key.compare("Backspace") == 0)
		{
			return SDLK_BACKSPACE;
		}
                else if(key.compare("Space") == 0)
		{
			return SDLK_SPACE;
		}
	}
	return SDLK_UNKNOWN;
}

void CSDLInputHandler::activateInput()
{
    m_isInputActivated = true;
}

void CSDLInputHandler::deactivateInput()
{
    m_isInputActivated = false;
}
